package asruby.runtime
{
import asruby.parser.StaticScope;
import asruby.runtime.scope.ManyVarsDynamicScope;
	
public class DynamicScope
{
   // Static scoping information for this scope
    protected var staticScope: StaticScope;
    
    // Captured dyanmic scopes
    protected var parent: DynamicScope;
    
    // A place to store that special hiding space that bindings need to implement things like:
    // var "a: eval = 1", binding); eval("p a").  All binding instances must get access to this
    // hidden shared scope.  We store it here.  This will be null if no binding has yet
    // been called.
    protected var evalScope: DynamicScope;

    public function DynamicScope( staticScope:StaticScope,  parent:DynamicScope=null) {
        this.staticScope = staticScope;
        this.parent = parent;
    }
    
    public static function  newDynamicScope(staticScope: StaticScope, parent: DynamicScope=null): DynamicScope {
        // Dynamic scopes with local static scopes must always
        // be ManyVarsDynamicScopes, since local scopes might grow
        // (e.g., when evaling the flip). See JRUBY-2046.
        if (staticScope.getLocalScope() == staticScope) {
            return new ManyVarsDynamicScope(staticScope, parent);
        }
		return new ManyVarsDynamicScope(staticScope, parent);
/*         switch (staticScope.getNumberOfVariables()) {
        case 0:
            return new NoVarsDynamicScope(staticScope, parent);
        case 1:
            return new OneVarDynamicScope(staticScope, parent);
        default:
            return new ManyVarsDynamicScope(staticScope, parent);
        } */
    }

    /**
     * Returns the n-th parent scope of this scope.
     * May return <code>null</code>.
     * @param n - number of levels above to look.
     * @return The n-th parent scope or <code>null</code>.
     */
    public function  getNthParentScope(n: int): DynamicScope {
        var scope: DynamicScope = this;
        for (var i: int = 0; i < n; i++) {
            if (scope != null) {
                scope = scope.getNextCapturedScope();
            } else {
                break;
            }
        }
        return scope;
    }

/*     public final function  getEvalScope(): DynamicScope {
        // We create one extra dynamicScope on a binding so that when we var "b: 'eval=1", binding' the
        // 'b' will get put into this new dynamic scope.  The original scope does not see the new
        // 'b' and successive evals with this binding will.  I take it having the ability to have 
        // succesive binding evals be able to share same scope makes sense from a programmers 
        // perspective.   One crappy outcome of this design is it requires Dynamic and Static 
        // scopes to be mutable for this one case.
        
        // Note: In Ruby 1.9 all of this logic can go away since they will require explicit
        // bindings for evals.
        
        // We only define one special dynamic scope per 'logical' binding.  So all bindings for
        // the same scope should share the same dynamic scope.  This allows multiple evals with
        // different different bindings in the same scope to see the same stuff.
        
        // No binding scope so we should create one
        if (evalScope == null) {
            // If the next scope out has the same binding scope as this scope it means
            // we are evaling within an eval and in that case we should be sharing the same
            // binding scope.
            var parent: DynamicScope = getNextCapturedScope();
            if (parent != null && parent.getEvalScope() == this) {
                evalScope = this;
            } else {
                // bindings scopes must always be ManyVars scopes since evals can grow them
                evalScope = new ManyVarsDynamicScope(new BlockStaticScope(getStaticScope()), this);
            }
        }
        
        return evalScope;
    } */
    
    /**
     * Get next 'captured' scope.
     * 
     * @return the scope captured by this scope for implementing closures
     *
     */
    public final function  getNextCapturedScope(): DynamicScope {
        return parent;
    }

    /**
     * Get the static scope associated with this DynamicScope.
     * 
     * @return static complement to this scope
     */
    public final function  getStaticScope(): StaticScope {
        return staticScope;
    }
    
    /**
     * Get all variable names captured (visible) by this scope (sans $~ and $_).
     * 
     * @return a list of variable names
     */
    public final function  getAllNamesInScope(): Array {
        return staticScope.getAllNamesInScope();
    }
    
    public function  toString(): String {
        return ""; //toString(new StringBuffer(), "");
    }

	public function cloneScope():DynamicScope {
		return null;
	}

    public function getValues():Array {
    	return null;
    }
    public function getValue(offset:int, depth:int):IRubyObject {
    	return null;
    }
    
    public function getValueOrNil(offset:int, depth:int,  nil:IRubyObject):IRubyObject {
    	return null;
    }
   
   	public function setValue(offset:int, value:IRubyObject, depth:int):void {
   	}
   	
   	public function getArgValues():Array {
   		return null;
   	}
   	public function setArgValues(values:Array, size:int):void {
   		
   	}

}
}